package com.pai4j.zwiki.service.agent;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.pai4j.zwiki.domain.entity.CodeStructureEntity;
import com.pai4j.zwiki.repository.CodeStructureRepository;
import com.pai4j.zwiki.service.LLMService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 代码关系图谱构建器
 * 
 * 核心功能：
 * 1. 构建类与类之间的依赖关系图谱
 * 2. 识别核心节点和关键路径
 * 3. 分析模块间的调用关系
 * 4. 检测循环依赖和紧密耦合
 * 5. 生成可视化的关系图谱数据
 * 6. 利用LLM理解复杂的调用链
 *
 * @author pai4j
 * @since 2025-10-14
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CodeRelationshipGraphBuilder {

    private final CodeStructureRepository codeStructureRepository;
    private final LLMService llmService;
    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 构建完整的代码关系图谱
     */
    public Map<String, Object> buildCodeRelationshipGraph(String taskId, String workspacePath) {
        log.info("开始构建代码关系图谱, 任务ID: {}", taskId);

        Map<String, Object> graphData = new HashMap<>();

        try {
            List<CodeStructureEntity> structures = codeStructureRepository.findByTaskId(taskId);

            // 1. 构建依赖关系图
            log.info("1. 构建类依赖关系图");
            Map<String, Set<String>> dependencyGraph = buildDependencyGraph(structures, workspacePath);
            graphData.put("dependencyGraph", dependencyGraph);

            // 2. 识别核心节点（被依赖最多的类）
            log.info("2. 识别核心节点");
            List<Map<String, Object>> coreNodes = identifyCoreNodes(dependencyGraph);
            graphData.put("coreNodes", coreNodes);

            // 3. 识别孤立节点（没有依赖关系的类）
            log.info("3. 识别孤立节点");
            List<String> isolatedNodes = identifyIsolatedNodes(structures, dependencyGraph);
            graphData.put("isolatedNodes", isolatedNodes);

            // 4. 检测循环依赖
            log.info("4. 检测循环依赖");
            List<List<String>> circularDependencies = detectCircularDependencies(dependencyGraph);
            graphData.put("circularDependencies", circularDependencies);

            // 5. 计算模块间耦合度
            log.info("5. 计算模块间耦合度");
            Map<String, Map<String, Integer>> moduleCoupling = calculateModuleCoupling(structures, dependencyGraph);
            graphData.put("moduleCoupling", moduleCoupling);

            // 6. 构建调用链路径
            log.info("6. 构建关键调用链");
            Map<String, List<String>> callPaths = buildKeyCallPaths(structures, dependencyGraph);
            graphData.put("callPaths", callPaths);

            // 7. 使用LLM分析关系图谱
            log.info("7. LLM分析关系图谱");
            String graphAnalysis = analyzeGraphWithLLM(graphData);
            graphData.put("llmGraphAnalysis", graphAnalysis);

            // 8. 生成Mermaid格式的关系图
            log.info("8. 生成Mermaid关系图");
            String mermaidGraph = generateMermaidGraph(dependencyGraph, coreNodes);
            graphData.put("mermaidGraph", mermaidGraph);

            log.info("代码关系图谱构建完成");

        } catch (Exception e) {
            log.error("构建代码关系图谱失败", e);
            graphData.put("error", e.getMessage());
        }

        return graphData;
    }

    /**
     * 构建依赖关系图（从import语句中提取）
     */
    private Map<String, Set<String>> buildDependencyGraph(List<CodeStructureEntity> structures, String workspacePath) {
        Map<String, Set<String>> graph = new HashMap<>();

        for (CodeStructureEntity structure : structures) {
            try {
                Path filePath = Paths.get(structure.getFilePath());
                if (!Files.exists(filePath)) continue;

                String code = Files.readString(filePath);
                String className = structure.getPackageName() + "." + structure.getName();

                // 提取import语句
                Set<String> dependencies = extractImports(code, structures);
                
                if (!dependencies.isEmpty()) {
                    graph.put(className, dependencies);
                }

            } catch (Exception e) {
                log.warn("分析类依赖失败: {}", structure.getName(), e);
            }
        }

        return graph;
    }

    /**
     * 从代码中提取import依赖
     */
    private Set<String> extractImports(String code, List<CodeStructureEntity> structures) {
        Set<String> imports = new HashSet<>();
        String[] lines = code.split("\n");

        // 构建项目类的全限定名集合
        Set<String> projectClasses = structures.stream()
                .map(s -> s.getPackageName() + "." + s.getName())
                .collect(Collectors.toSet());

        for (String line : lines) {
            String trimmed = line.trim();
            if (trimmed.startsWith("import ") && !trimmed.contains("import static")) {
                String importClass = trimmed
                        .replace("import ", "")
                        .replace(";", "")
                        .trim();

                // 只保留项目内部的类
                if (projectClasses.contains(importClass)) {
                    imports.add(importClass);
                }
            }
        }

        return imports;
    }

    /**
     * 识别核心节点（被依赖最多的类）
     */
    private List<Map<String, Object>> identifyCoreNodes(Map<String, Set<String>> dependencyGraph) {
        Map<String, Integer> inDegree = new HashMap<>();

        // 计算入度（被依赖次数）
        for (Set<String> dependencies : dependencyGraph.values()) {
            for (String dep : dependencies) {
                inDegree.put(dep, inDegree.getOrDefault(dep, 0) + 1);
            }
        }

        // 排序并取前20个
        return inDegree.entrySet().stream()
                .sorted((e1, e2) -> Integer.compare(e2.getValue(), e1.getValue()))
                .limit(20)
                .map(entry -> {
                    Map<String, Object> node = new HashMap<>();
                    node.put("className", entry.getKey());
                    node.put("dependencyCount", entry.getValue());
                    node.put("importance", calculateImportanceScore(entry.getValue()));
                    return node;
                })
                .collect(Collectors.toList());
    }

    /**
     * 识别孤立节点
     */
    private List<String> identifyIsolatedNodes(List<CodeStructureEntity> structures, 
                                                Map<String, Set<String>> dependencyGraph) {
        Set<String> allClasses = structures.stream()
                .map(s -> s.getPackageName() + "." + s.getName())
                .collect(Collectors.toSet());

        Set<String> connectedClasses = new HashSet<>();
        connectedClasses.addAll(dependencyGraph.keySet());
        dependencyGraph.values().forEach(connectedClasses::addAll);

        List<String> isolated = new ArrayList<>(allClasses);
        isolated.removeAll(connectedClasses);

        return isolated;
    }

    /**
     * 检测循环依赖（使用DFS）
     */
    private List<List<String>> detectCircularDependencies(Map<String, Set<String>> dependencyGraph) {
        List<List<String>> cycles = new ArrayList<>();
        Set<String> visited = new HashSet<>();
        Set<String> recursionStack = new HashSet<>();
        List<String> currentPath = new ArrayList<>();

        for (String node : dependencyGraph.keySet()) {
            if (!visited.contains(node)) {
                detectCyclesDFS(node, dependencyGraph, visited, recursionStack, currentPath, cycles);
            }
        }

        return cycles;
    }

    /**
     * DFS检测循环依赖
     */
    private void detectCyclesDFS(String node, Map<String, Set<String>> graph,
                                  Set<String> visited, Set<String> recursionStack,
                                  List<String> currentPath, List<List<String>> cycles) {
        visited.add(node);
        recursionStack.add(node);
        currentPath.add(node);

        Set<String> neighbors = graph.getOrDefault(node, Collections.emptySet());
        for (String neighbor : neighbors) {
            if (!visited.contains(neighbor)) {
                detectCyclesDFS(neighbor, graph, visited, recursionStack, currentPath, cycles);
            } else if (recursionStack.contains(neighbor)) {
                // 发现循环
                int cycleStart = currentPath.indexOf(neighbor);
                if (cycleStart >= 0) {
                    List<String> cycle = new ArrayList<>(currentPath.subList(cycleStart, currentPath.size()));
                    cycle.add(neighbor);
                    if (cycle.size() <= 10) { // 只记录较小的循环
                        cycles.add(cycle);
                    }
                }
            }
        }

        currentPath.remove(currentPath.size() - 1);
        recursionStack.remove(node);
    }

    /**
     * 计算模块间耦合度
     */
    private Map<String, Map<String, Integer>> calculateModuleCoupling(
            List<CodeStructureEntity> structures,
            Map<String, Set<String>> dependencyGraph) {
        
        Map<String, Map<String, Integer>> coupling = new HashMap<>();

        // 按包分组
        Map<String, List<String>> packageClasses = structures.stream()
                .collect(Collectors.groupingBy(
                        CodeStructureEntity::getPackageName,
                        Collectors.mapping(s -> s.getPackageName() + "." + s.getName(), 
                                         Collectors.toList())
                ));

        // 计算包与包之间的依赖次数
        for (Map.Entry<String, List<String>> entry : packageClasses.entrySet()) {
            String sourcePackage = entry.getKey();
            Map<String, Integer> targetCoupling = new HashMap<>();

            for (String sourceClass : entry.getValue()) {
                Set<String> deps = dependencyGraph.getOrDefault(sourceClass, Collections.emptySet());
                
                for (String dep : deps) {
                    String targetPackage = extractPackageName(dep);
                    if (!targetPackage.equals(sourcePackage)) {
                        targetCoupling.put(targetPackage, 
                                         targetCoupling.getOrDefault(targetPackage, 0) + 1);
                    }
                }
            }

            if (!targetCoupling.isEmpty()) {
                coupling.put(sourcePackage, targetCoupling);
            }
        }

        return coupling;
    }

    /**
     * 构建关键调用链路径
     */
    private Map<String, List<String>> buildKeyCallPaths(List<CodeStructureEntity> structures,
                                                          Map<String, Set<String>> dependencyGraph) {
        Map<String, List<String>> callPaths = new HashMap<>();

        // 识别Controller作为入口点
        List<String> controllers = structures.stream()
                .filter(s -> s.getName().endsWith("Controller"))
                .map(s -> s.getPackageName() + "." + s.getName())
                .collect(Collectors.toList());

        // 为每个Controller构建调用路径
        for (String controller : controllers) {
            List<String> path = traceCallPath(controller, dependencyGraph, new HashSet<>(), 5);
            if (!path.isEmpty()) {
                callPaths.put(controller, path);
            }
        }

        return callPaths;
    }

    /**
     * 追踪调用路径（BFS，限制深度）
     */
    private List<String> traceCallPath(String startNode, Map<String, Set<String>> graph,
                                        Set<String> visited, int maxDepth) {
        List<String> path = new ArrayList<>();
        Queue<String> queue = new LinkedList<>();
        Map<String, Integer> depths = new HashMap<>();

        queue.offer(startNode);
        visited.add(startNode);
        depths.put(startNode, 0);
        path.add(startNode);

        while (!queue.isEmpty() && path.size() < 20) {
            String current = queue.poll();
            int currentDepth = depths.get(current);

            if (currentDepth >= maxDepth) {
                continue;
            }

            Set<String> neighbors = graph.getOrDefault(current, Collections.emptySet());
            for (String neighbor : neighbors) {
                if (!visited.contains(neighbor)) {
                    visited.add(neighbor);
                    queue.offer(neighbor);
                    depths.put(neighbor, currentDepth + 1);
                    path.add(neighbor);
                }
            }
        }

        return path;
    }

    /**
     * 使用LLM分析关系图谱
     */
    private String analyzeGraphWithLLM(Map<String, Object> graphData) {
        StringBuilder prompt = new StringBuilder();
        prompt.append("请分析以下代码关系图谱，深入理解系统的结构和交互：\n\n");

        // 核心节点信息
        @SuppressWarnings("unchecked")
        List<Map<String, Object>> coreNodes = (List<Map<String, Object>>) graphData.get("coreNodes");
        if (coreNodes != null && !coreNodes.isEmpty()) {
            prompt.append("## 核心节点（被依赖最多的类）\n\n");
            for (int i = 0; i < Math.min(10, coreNodes.size()); i++) {
                Map<String, Object> node = coreNodes.get(i);
                prompt.append(String.format("- %s (被依赖 %d 次)\n", 
                        node.get("className"), node.get("dependencyCount")));
            }
            prompt.append("\n");
        }

        // 循环依赖
        @SuppressWarnings("unchecked")
        List<List<String>> cycles = (List<List<String>>) graphData.get("circularDependencies");
        if (cycles != null && !cycles.isEmpty()) {
            prompt.append("## 循环依赖（需要关注）\n\n");
            for (int i = 0; i < Math.min(5, cycles.size()); i++) {
                List<String> cycle = cycles.get(i);
                prompt.append(String.format("- 循环 %d: %s\n", i + 1, String.join(" → ", cycle)));
            }
            prompt.append("\n");
        }

        // 调用路径
        @SuppressWarnings("unchecked")
        Map<String, List<String>> callPaths = (Map<String, List<String>>) graphData.get("callPaths");
        if (callPaths != null && !callPaths.isEmpty()) {
            prompt.append("## 主要调用路径\n\n");
            callPaths.entrySet().stream().limit(5).forEach(entry -> {
                prompt.append(String.format("- %s:\n  %s\n", 
                        simplifyClassName(entry.getKey()),
                        String.join(" → ", entry.getValue().stream()
                                .map(this::simplifyClassName)
                                .limit(8)
                                .collect(Collectors.toList()))));
            });
            prompt.append("\n");
        }

        prompt.append("""
                ---
                
                请深入分析：
                
                ## 1. 架构洞察（30%）
                - 从依赖关系看，这是什么架构风格？
                - 模块划分是否合理？
                - 分层是否清晰？
                
                ## 2. 核心组件分析（25%）
                - 为什么这些类是核心节点？它们的共同特点是什么？
                - 核心节点的设计是否稳定？
                - 是否存在过度依赖某个类的情况？
                
                ## 3. 耦合度评估（25%）
                - 整体耦合度如何？
                - 哪些模块之间耦合度过高？
                - 循环依赖说明了什么问题？如何解决？
                
                ## 4. 调用链分析（20%）
                - 主要的业务调用流程是怎样的？
                - 调用链是否过长或过于复杂？
                - 是否有优化空间？
                
                请详细分析（1000-1500字）。
                """);

        try {
            return llmService.generateCodeSummary(prompt.toString());
        } catch (Exception e) {
            log.error("LLM分析关系图谱失败", e);
            return "图谱分析失败: " + e.getMessage();
        }
    }

    /**
     * 生成Mermaid格式的关系图
     */
    private String generateMermaidGraph(Map<String, Set<String>> dependencyGraph,
                                        List<Map<String, Object>> coreNodes) {
        StringBuilder mermaid = new StringBuilder();
        mermaid.append("```mermaid\n");
        mermaid.append("graph LR\n");

        // 提取核心节点ID
        Set<String> coreNodeIds = coreNodes.stream()
                .limit(15)
                .map(n -> (String) n.get("className"))
                .collect(Collectors.toSet());

        // 只显示核心节点及其直接关系
        int nodeId = 0;
        Map<String, String> nodeIdMap = new HashMap<>();

        for (String coreNode : coreNodeIds) {
            String id = "N" + (nodeId++);
            nodeIdMap.put(coreNode, id);
            mermaid.append(String.format("    %s[%s]\n", id, simplifyClassName(coreNode)));
        }

        // 添加边（只显示核心节点之间的依赖）
        for (String source : coreNodeIds) {
            Set<String> targets = dependencyGraph.getOrDefault(source, Collections.emptySet());
            for (String target : targets) {
                if (coreNodeIds.contains(target)) {
                    String sourceId = nodeIdMap.get(source);
                    String targetId = nodeIdMap.get(target);
                    mermaid.append(String.format("    %s --> %s\n", sourceId, targetId));
                }
            }
        }

        mermaid.append("```\n");
        return mermaid.toString();
    }

    // ========== 辅助方法 ==========

    private String extractPackageName(String fullClassName) {
        int lastDot = fullClassName.lastIndexOf('.');
        return lastDot > 0 ? fullClassName.substring(0, lastDot) : "";
    }

    private String simplifyClassName(String fullClassName) {
        int lastDot = fullClassName.lastIndexOf('.');
        return lastDot > 0 ? fullClassName.substring(lastDot + 1) : fullClassName;
    }

    private double calculateImportanceScore(int dependencyCount) {
        // 归一化到0-10分
        return Math.min(10.0, dependencyCount / 2.0);
    }
}

